package com.ccl.iot.managers;

import android.content.Context;
import android.os.Environment;
import android.util.Log;

import com.ccl.iot.IOTCallback;
import com.ccl.iot.IOTNetAPI;
import com.ccl.iot.batch.IOTBatch;
import com.ccl.iot.ir.BroadLinkManager;
import com.ccl.iot.monitor.NetworkMonitor;
import com.ccl.iot.monitor.ScreenMonitor;
import com.ccl.iot.privates.APIConst;
import com.ccl.iot.privates.InfoProcessor;
import com.ccl.iot.publics.Debugger;
import com.ccl.iot.publics.Messager;
import com.ccl.iot.publics.SPUtil;
import com.ccl.iot.publics.ThreadPoolUtils;
import com.ccl.iot.template.StandardActivity;

import java.io.File;
import java.util.ArrayList;

public class MainManager extends Manager {
    public static final String KDEFAULT_DATABASE_PATH = Environment.getExternalStorageDirectory().getPath() + "/CCL2/IOT2/";

    /*
     * 	Static functions
     */
    public static boolean Prepare() {
        return Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);
    }

    private static MainManager gDefault = null;

    public static MainManager GetDefaultManager(Context aContext) {
        if (gDefault == null) {
            SPUtil.init();
            gDefault = new MainManager(aContext);
        }

        return gDefault;
    }

    public static MainManager GetDefaultManager() {
        return gDefault;
    }

    public static void Suspend() {
        if (gDefault != null) {
            gDefault.suspend();
        }
    }

    /*
     * 	Non-static functions
     */
    private IOTNetAPI iNetAPI = null;
    private BatchManager iBatchManager = null;
    private ArrayList<Manager> iManagerList = null;

    private boolean iSelfSuspend = false;

    private MainManager(Context aContext) {
        super(aContext);

        File tDBPath = new File(KDEFAULT_DATABASE_PATH);
        if (tDBPath.exists() == false) {
            tDBPath.mkdirs();
        }

        IOTNetAPI.Initialize(KDEFAULT_DATABASE_PATH, iErrorListener);

        initialize(aContext);
        super.create();
    }

    private void initialize(Context aContext) {
        iNetAPI = IOTNetAPI.GetInstance();

        iManagerList = new ArrayList<Manager>();

        ImageManager.Initialize(KDEFAULT_DATABASE_PATH);
        iManagerList.add(UserManager.GetDefaultManager(aContext, KDEFAULT_DATABASE_PATH));


        InfoProcessor.init();
        iManagerList.add(AuthManager.GetDefaultManager(aContext));
        DeviceManager deviceManager = DeviceManager.GetDefaultManager(aContext);
        iManagerList.add(RegisterManager.GetDefaultManager(aContext));
        iManagerList.add(deviceManager);
        deviceManager.loadCacheDevs();
        iManagerList.add(iBatchManager = BatchManager.GetDefaultManager(aContext));

        BLUserInfoMamager.Init(aContext);
        BroadLinkManager.Init(aContext);

        ScreenMonitor.AddOnScreenChangeListener(iScreenChangeListener);

        NetworkMonitor.AddOnNetworkStateChangeListener(iNetworkListener);

        StandardActivity.SetActivityStateChangeListener(iActivityStateChangeListener);


    }

    private IOTCallback.ErrorCallback iErrorListener = new IOTCallback.ErrorCallback() {
        @Override
        public void onError(String aAction, int aErrorCode) {
            String tError = (aAction != null ? aAction : "") + " error: 0x" + Integer.toHexString(aErrorCode);

            //			if (iManagerList != null) {
            //				for (int i = iManagerList.size() - 1; i >= 0; i--) {
            //					if (iManagerList.get(i).filteError(aErrorCode)) {
            //						// Debugger.Warning(tError + " filted");
            //
            //						return;
            //					}
            //				}
            //			}

            {
                // Debugger.Error(tError);
                // Messager.Show(tError);

                String error = APIConst.getString(aErrorCode);
                Log.e("onError", "Error: "+error+", ErrorCode: "+Integer.toHexString(aErrorCode));
                if (error == null) {
                    Debugger.Error(tError);
                } else {
                    Debugger.Error(error);
                    Messager.Show(error, 0);
                }

            }
        }
    };

    private void resumeOrSuspend(boolean aResume) {
        if (aResume) {
            if (iSelfSuspend) {
                if (isSuspend() && isBackground(true) == false) {
                    resume();
                }

                iSelfSuspend = false;
            }
        } else {
            if (isSuspend() == false) {
                suspend();
                iSelfSuspend = true;
            }
        }
    }

    private ScreenMonitor.OnScreenChangeListener iScreenChangeListener = new ScreenMonitor.OnScreenChangeListener() {
        @Override
        public void onScreenChange(boolean aOn) {
            resumeOrSuspend(aOn);
        }
    };

    private NetworkMonitor.OnNetwrokStateChangeListener iNetworkListener = new NetworkMonitor.OnNetwrokStateChangeListener() {

        @Override
        public void onNetworkStateChange(NetworkMonitor aMonitor, final boolean aConnected) {
            Log.e("NETWORK", "onNetworkStateChange aConnected: "+aConnected);

            resumeOrSuspend(aConnected);
            if (aConnected) {
                iNetAPI.setBroadcastEnabled(NetworkMonitor.IsConnectedByMobile() == false);
            }
        }
    };

    private StandardActivity.OnActivityStateChangeListener iActivityStateChangeListener = new StandardActivity.OnActivityStateChangeListener() {
        @Override
        public void onActivityStateChange(StandardActivity aActivity, int aState) {
            if (aState == StandardActivity.KACTIVITY_STATE_STOPPED) {
                if (StandardActivity.getShowing() == null) {
                    synchronized (iActivityStateChangeListener) {
                        if (isSuspend() == false) {
                            Debugger.Warning("Suspend when all activity stoped");
                            suspend();
                        }
                    }
                }
            } else if (aState == StandardActivity.KACTIVITY_STATE_RESUMING) {
                synchronized (iActivityStateChangeListener) {
                    if (isSuspend()) {
                        Debugger.Warning("Resume when activity resume");
                        resume();
                    }
                }
            }
        }
    };


    @Override
    public void onResume() {
        super.onResume();

        iNetAPI.setBroadcastEnabled(NetworkMonitor.IsConnectedByMobile() == false);

        // TODO MainManager 使用线程池

		/*new Thread(new Runnable(){
            @Override
			public void run() {
				if (isSuspend() == false){
					if (iNetAPI.isStarted() == false){
						iNetAPI.startUp();	
					}
		
					if (iManagerList != null){
						for (int i = iManagerList.size() - 1; i >= 0 && isSuspend() == false; i--){
							iManagerList.get(i).resume();
						}
					}
				}
			}
		}, "Manager resume").start();*/

        // ===================start=========================
        ThreadPoolUtils.getInstance().addTask(new Runnable() {

            @Override
            public void run() {
                if (isSuspend() == false) {
                    if (iNetAPI.isStarted() == false) {
                        iNetAPI.startUp();
                    }

                    if (iManagerList != null) {
                        for (int i = iManagerList.size() - 1; i >= 0 && isSuspend() == false; i--) {
                            iManagerList.get(i).resume();
                        }
                    }
                }
            }
        });
        // ===================end=========================

    }

    @Override
    public void onSuspend() {
        super.onSuspend();

        if (iManagerList != null) {
            for (int i = iManagerList.size() - 1; i >= 0; i--) {
                iManagerList.get(i).suspend();
            }
        }
        iNetAPI.shutdown();
    }

    public ArrayList<Object> findRelativedObject(Object aObject) {
        if (aObject != null) {
            ArrayList<Object> tRelatived = new ArrayList<Object>();

            if (tRelatived.size() > 0) {
                for (int i = tRelatived.size() - 1; i >= 0; i--) {
                    ArrayList<Object> tSubRelatived = findRelativedObject(tRelatived.get(i));

                    if (tSubRelatived != null) {
                        tRelatived.addAll(tSubRelatived);
                    }
                }

                return tRelatived;
            }
        }

        return null;
    }

    public boolean removeRelativedObject(Object aObject) {
        if (aObject != null) {
            boolean tOK = true;
            ArrayList<Object> tRelatived = findRelativedObject(aObject);

            if (tRelatived != null) {
                for (int i = tRelatived.size() - 1; i >= 0; i--) {
                    tOK &= removeRelativedObject(tRelatived.get(i));
                }
            }

            if (aObject instanceof IOTBatch) {
                if (iBatchManager != null) {
                    tOK &= iBatchManager.removeBatch((IOTBatch) aObject);
                }
            }

            return tOK;
        }

        return false;
    }
}
